package com.baoleme.baoleme_goods_service.service.impl;

import com.baoleme.baoleme_goods_service.mapper.SetMealGoodsMapper;
import com.baoleme.baoleme_goods_service.mapper.SetMealMapper;
import com.baoleme.baoleme_goods_service.service.CategoryService;
import com.baoleme.baoleme_goods_service.service.GoodsService;
import com.baoleme.baoleme_goods_service.service.SetMealGoodsService;
import com.baoleme.baoleme_goods_service.service.SetMealService;
import com.baoleme.exceptions.BusinessException;
import com.baoleme.exceptions.enumeration.ResponseEnum;
import com.baoleme_goods_model.dto.SetMealDTO;
import com.baoleme_goods_model.dto.SetMealGoodsDTO;
import com.baoleme_goods_model.entity.Category;
import com.baoleme_goods_model.entity.Goods;
import com.baoleme_goods_model.entity.SetMeal;
import com.baoleme_goods_model.entity.SetMealGoods;
import com.baoleme_goods_model.vo.SetMealForClientVO;
import com.baoleme_goods_model.vo.SetMealGoodsForClientVO;
import com.baoleme_goods_model.vo.SetMealGoodsVO;
import com.baoleme_goods_model.vo.SetMealVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author wuyunbin
 * @since 2024-09-13
 */
@Service
@Slf4j
public class SetMealServiceImpl extends ServiceImpl<SetMealMapper, SetMeal> implements SetMealService {

    @Resource
    private SetMealMapper setMealMapper;
    @Resource
    private SetMealGoodsMapper setMealGoodsMapper;
    @Resource
    private SetMealGoodsService setMealGoodsService;
    @Resource
    private CategoryService categoryService;
    @Resource
    private GoodsService goodsService;

    @Override
    public boolean updateSetMeal(SetMealDTO setMealDTO) {
        // 修改set_meal表
        SetMeal setMeal = new SetMeal();
        setMeal.setId(setMealDTO.getId());
        setMeal.setName(setMealDTO.getName());
        setMeal.setImage(setMealDTO.getImage());
        setMeal.setPrice(setMealDTO.getPrice());
        setMeal.setStatus(setMealDTO.getStatus());
        setMeal.setCategoryId(setMealDTO.getCategoryId());
        setMeal.setDescription(setMealDTO.getDescription());

        int flag = setMealMapper.updateById(setMeal);
        if (flag<=0){
            return false;
        }

        // 修改set_meal_goods表
        for (SetMealGoodsDTO setMealGoodsDTO : setMealDTO.getSetMealGoods()) {
            SetMealGoods setMealGoods = new SetMealGoods();
            setMealGoods.setId(setMealGoodsDTO.getId());
            setMealGoods.setName(setMealGoodsDTO.getName());
            setMealGoods.setPrice(setMealGoodsDTO.getPrice());
            setMealGoods.setCopies(setMealGoodsDTO.getCopies());
            setMealGoods.setGoodsId(setMealGoodsDTO.getGoodsId());
            setMealGoods.setSetMealId(setMealGoodsDTO.getSetMealId());
            boolean flag2 = setMealGoodsMapper.insertOrUpdate(setMealGoods);
            if (!flag2){
                return false;
            }
        }

        return true;
    }

    @Transactional
    @Override
    public boolean removeWithGoods(List<String> ids) {
        // 这些id中如果有一个套餐是在售状态，就都不能删除
            // 1.查询套餐在售状态
        LambdaQueryWrapper<SetMeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(SetMeal::getId,ids);
        wrapper.eq(SetMeal::getStatus,1);
        long count = this.count(wrapper);
        if (count > 0){
            throw new BusinessException(ResponseEnum.SET_MEAL_STILL_IN_SALE);
        }

            // 2.全为停售状态，就可以批量删除（PS:使用逻辑删除，修改is_deleted字段）
                // 1.在set_meal表删除
        wrapper.clear();
        wrapper.in(SetMeal::getId,ids);
        SetMeal setMeal = new SetMeal();
        setMeal.setIsDeleted(1);
        boolean flag1 = this.update(setMeal, wrapper);

        // 2.在set_meal_goods表删除
        LambdaQueryWrapper<SetMealGoods> wrapper2 = new LambdaQueryWrapper<>();
        wrapper2.in(SetMealGoods::getSetMealId,ids);
        SetMealGoods setMealGoods = new SetMealGoods();
        setMealGoods.setIsDeleted(1);
        boolean flag2 = setMealGoodsMapper.update(setMealGoods, wrapper2)>0;
        return flag1&&flag2;
    }

    @Override
    public boolean saveSetMeal(SetMealDTO setMealDTO) {
        // 在set_meal表插入
        SetMeal setMeal = new SetMeal();
        // 新增，不需要id
        /*setMeal.setId(setMealDTO.getId());*/
        setMeal.setName(setMealDTO.getName());
        setMeal.setImage(setMealDTO.getImage());
        setMeal.setPrice(setMealDTO.getPrice());
        setMeal.setStatus(setMealDTO.getStatus());
        setMeal.setCategoryId(setMealDTO.getCategoryId());
        setMeal.setDescription(setMealDTO.getDescription());

        boolean flag1 = this.save(setMeal);
        log.info("flag1:{}",flag1);


        // 这里用 MyBatis-Plus 自带的雪花算法自动生成的id
        // MyBatis-Plus 在执行插入操作后会将生成的主键值设置到对应的对象字段中。


        // 在set_meal_goods表插入对应商品

        List<SetMealGoodsDTO> setMealGoodsDTOList = setMealDTO.getSetMealGoods();
        List<SetMealGoods> setMealGoodsList = new ArrayList<>();
        for (SetMealGoodsDTO setMealGoodsDTO : setMealGoodsDTOList) {
            SetMealGoods setMealGoods = new SetMealGoods();
            setMealGoods.setId(setMealGoodsDTO.getId());
            setMealGoods.setName(setMealGoodsDTO.getName());
            setMealGoods.setPrice(setMealGoodsDTO.getPrice());
            setMealGoods.setCopies(setMealGoodsDTO.getCopies());
            setMealGoods.setGoodsId(setMealGoodsDTO.getGoodsId());
            setMealGoods.setSetMealId(setMeal.getId());
            setMealGoodsList.add(setMealGoods);
        }


        boolean flag2 = setMealGoodsService.saveBatch(setMealGoodsList);

        return flag1&&flag2;

    }

    @Override
    public SetMealVO getWithGoodsById(String id) {

        // 去set_meal表查询
        SetMeal setMeal = this.getById(id);
        // 拿categoryId去category表查找categoryName
        Category category = categoryService.getById(setMeal.getCategoryId());

        String categoryName = category.getName();

        // 去 set_meal_goods表里根据categoryId查找对应商品
        LambdaQueryWrapper<SetMealGoods> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetMealGoods::getSetMealId,setMeal.getId());
        List<SetMealGoods> setMealGoodsList = setMealGoodsService.list(wrapper);
        List<SetMealGoodsVO> setMealGoodsVOList = setMealGoodsList.stream()
                .map((setMealGoods) -> {
                    SetMealGoodsVO setMealGoodsVO = new SetMealGoodsVO();
                    setMealGoodsVO.setId(setMealGoods.getId());
                    setMealGoodsVO.setName(setMealGoods.getName());
                    setMealGoodsVO.setPrice(setMealGoods.getPrice());
                    setMealGoodsVO.setCopies(setMealGoods.getCopies());
                    setMealGoodsVO.setGoodsId(setMealGoods.getGoodsId());
                    setMealGoodsVO.setSetMealId(setMealGoods.getSetMealId());
                    return setMealGoodsVO;
                })
                .collect(Collectors.toList());

        // 最后装到 SetMealVO 对象里，并返回
        SetMealVO setMealVO = new SetMealVO();

        setMealVO.setId(setMeal.getId());
        setMealVO.setName(setMeal.getName());
        setMealVO.setImage(setMeal.getImage());
        setMealVO.setPrice(setMeal.getPrice());
        setMealVO.setStatus(setMeal.getStatus());
        setMealVO.setCategoryId(setMeal.getCategoryId());
        setMealVO.setCategoryName(categoryName);
        setMealVO.setUpdateTime(setMeal.getUpdateTime());
        setMealVO.setDescription(setMeal.getDescription());
        setMealVO.setSetMealGoodsVOList(setMealGoodsVOList);

        return setMealVO;
    }

    @Override
    public List<SetMealForClientVO> getByCategoryId(String categoryId) {
        LambdaQueryWrapper<SetMeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(SetMeal::getCategoryId, categoryId);
        List<SetMeal> list = this.list(wrapper);

        return list.stream().map((setMeal) -> {
            SetMealForClientVO setMealForClientVO = new SetMealForClientVO();

            setMealForClientVO.setId(setMeal.getId());
            setMealForClientVO.setName(setMeal.getName());
            setMealForClientVO.setImage(setMeal.getImage());
            setMealForClientVO.setPrice(setMeal.getPrice());
            setMealForClientVO.setStatus(setMeal.getStatus());
            setMealForClientVO.setCategoryId(categoryId);
            setMealForClientVO.setCreateTime(setMeal.getCreateTime());
            setMealForClientVO.setCreateUser(setMeal.getCreateUser());
            setMealForClientVO.setUpdateTime(setMeal.getUpdateTime());
            setMealForClientVO.setUpdateUser(setMeal.getUpdateUser());
            setMealForClientVO.setDescription(setMeal.getDescription());
            return setMealForClientVO;
        }).collect(Collectors.toList());
    }

    @Override
    public List<SetMealGoodsForClientVO> getSetMealGoodsBySetMealId(String id) {
        // 从set_meal_goods查询
        LambdaQueryWrapper<SetMealGoods> wrapper1 = new LambdaQueryWrapper<>();
        wrapper1.eq(SetMealGoods::getSetMealId,id);
        List<SetMealGoods> list = setMealGoodsService.list(wrapper1);

        // 想从set_meal_goods表获得什么？
        // - goods_id、name、copies
        // - 用 Map<String,SetMealGoodsForClientVO> 装试试
        // - key是goods_id
        Map<String,SetMealGoods> map = new HashMap<>();

        for (SetMealGoods setMealGoods : list) {
            map.put(setMealGoods.getGoodsId(),setMealGoods);
        }

        List<SetMealGoodsForClientVO> setMealGoodsForClientVOList = new ArrayList<>();
        for (String goodsId : map.keySet()) {
            Goods goods = goodsService.getById(goodsId);
            SetMealGoodsForClientVO setMealGoodsForClientVO = new SetMealGoodsForClientVO();
            setMealGoodsForClientVO.setImage(goods.getImage());
            setMealGoodsForClientVO.setDescription(goods.getDescription());
            setMealGoodsForClientVO.setName(map.get(goodsId).getName());
            setMealGoodsForClientVO.setCopies(map.get(goodsId).getCopies());
            setMealGoodsForClientVOList.add(setMealGoodsForClientVO);
        }

        return setMealGoodsForClientVOList;
    }
}
